home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / kernel / mach / ds5000.md / machAsm.s < prev    next >
Encoding:
Text File  |  1993-01-07  |  53.0 KB  |  2,178 lines

  1. /*
  2.  * machAsm.s --
  3.  *
  4.  *    Contains misc. assembler routines for the PMAX.
  5.  *
  6.  *    Copyright (C) 1989 Digital Equipment Corporation.
  7.  *    Permission to use, copy, modify, and distribute this software and
  8.  *    its documentation for any purpose and without fee is hereby granted,
  9.  *    provided that the above copyright notice appears in all copies.  
  10.  *    Digital Equipment Corporation makes no representations about the
  11.  *    suitability of this software for any purpose.  It is provided "as is"
  12.  *    without express or implied warranty.
  13.  *
  14.  * $Header: /cdrom/src/kernel/Cvsroot/kernel/mach/ds5000.md/machAsm.s,v 1.14 93/01/06 16:38:57 jhh Exp $ SPRITE (DECWRL)
  15.  */
  16.  
  17. #include "machConst.h"
  18. #include "machAsmDefs.h"
  19. #include "vm3maxConst.h"
  20. #include <regdef.h>
  21.  
  22. /*----------------------------------------------------------------------------
  23.  *
  24.  * MachConfigCache --
  25.  *
  26.  *    Size the caches.
  27.  *
  28.  * Results:
  29.  *         None.
  30.  *
  31.  * Side effects:
  32.  *    The size of the data cache stored into machDataCacheSize and the
  33.  *    size of instruction cache stored into machInstCacheSize.
  34.  *
  35.  *----------------------------------------------------------------------------
  36.  */
  37. CONFIG_FRAME=    (4*4)+4+4        # 4 arg saves, ra, and a saved register
  38.     .globl    MachConfigCache
  39. MachConfigCache:
  40.     subu    sp,CONFIG_FRAME
  41.     sw    ra,CONFIG_FRAME-4(sp)        # Save return address.
  42.     sw    s0,CONFIG_FRAME-8(sp)        # Save s0 on stack.
  43.     mfc0    s0,MACH_COP_0_STATUS_REG    # Save status register.
  44.     mtc0    zero,MACH_COP_0_STATUS_REG    # Disable interrupts.
  45.     .set    noreorder
  46.     la    v0,1f
  47.     or    v0,VMMACH_PHYS_UNCACHED_START    # Run uncached.
  48.     j    v0
  49.     nop
  50.  
  51. 1:    jal    SizeCache            # Get the size of the d-cache.
  52.     nop
  53.     sw    v0,machDataCacheSize
  54.     nop                    # Make sure sw out of pipe
  55.     nop
  56.     nop
  57.     nop
  58.     li    v0,MACH_SR_SWAP_CACHES        # Swap caches
  59.     mtc0    v0,MACH_COP_0_STATUS_REG
  60.     nop                    # Insure caches stable
  61.     nop
  62.     nop
  63.     nop
  64.     jal    SizeCache            # Get the size of the i-cache.
  65.     nop
  66.     sw    v0,machInstCacheSize        
  67.     nop                    # Make sure sw out of pipe
  68.     nop
  69.     nop
  70.     nop
  71.     mtc0    zero, MACH_COP_0_STATUS_REG    # Swap back caches. 
  72.     nop
  73.     nop
  74.     nop
  75.     nop
  76.     la    t0,1f
  77.     j    t0                # Back to cached mode
  78.     nop
  79.  
  80. 1:    mtc0    s0,MACH_COP_0_STATUS_REG    # Restore status register.
  81.     nop
  82.     lw    s0,CONFIG_FRAME-8(sp)        # Restore old s0
  83.     lw    ra,CONFIG_FRAME-4(sp)        # Restore return addr
  84.     addu    sp,CONFIG_FRAME            # Restore sp.
  85.     j    ra
  86.     nop
  87.     .set    reorder
  88.  
  89. /*----------------------------------------------------------------------------
  90.  *
  91.  * SizeCache --
  92.  *
  93.  *    Get the size of the cache.
  94.  *
  95.  * Results:
  96.  *         The size of the cache.
  97.  *
  98.  * Side effects:
  99.  *    None.
  100.  *
  101.  *----------------------------------------------------------------------------
  102.  */
  103. SizeCache:
  104.     .set    noreorder
  105.     mfc0    t0,MACH_COP_0_STATUS_REG    # Save the current status reg.
  106.     nop                
  107.     or    v0,t0,MACH_SR_ISOL_CACHES    # Isolate the caches.
  108.     nop                    # Make sure no stores in pipe
  109.     mtc0    v0,MACH_COP_0_STATUS_REG
  110.     nop                    # Make sure isolated
  111.     nop
  112.     nop
  113.     /*
  114.      * Clear cache size boundaries.
  115.      */
  116.     li    v0, MACH_MIN_CACHE_SIZE
  117. 1:
  118.     sw    zero, VMMACH_PHYS_CACHED_START(v0)
  119.     sll    v0,1
  120.     ble    v0,+MACH_MAX_CACHE_SIZE,1b
  121.     nop
  122.     li    v0,-1
  123.     sw    v0, VMMACH_PHYS_CACHED_START(zero)    # Store marker in cache
  124.     li    v0, MACH_MIN_CACHE_SIZE
  125.  
  126. 2:    lw    v1, VMMACH_PHYS_CACHED_START(v0)    # Look for marker
  127.     nop            
  128.     bne    v1,zero,3f                # Found marker.
  129.     nop
  130.  
  131.     sll    v0,1            # cache size * 2
  132.     ble    v0,+MACH_MAX_CACHE_SIZE,2b        # keep looking
  133.     nop
  134.     move    v0,zero            # must be no cache
  135.     .set    reorder
  136.  
  137. 3:    mtc0    t0,MACH_COP_0_STATUS_REG
  138.     nop                # Make sure unisolated
  139.     nop
  140.     nop
  141.     nop
  142.     j    ra
  143.     nop
  144. .set reorder
  145.  
  146. /*----------------------------------------------------------------------------
  147.  *
  148.  * MachFlushCache --
  149.  *
  150.  *    Flush the caches.
  151.  *
  152.  * Results:
  153.  *         None.
  154.  *
  155.  * Side effects:
  156.  *    The contents of the cache is flushed.
  157.  *
  158.  *----------------------------------------------------------------------------
  159.  */
  160.     .globl    MachFlushCache
  161. MachFlushCache:
  162.     lw    t1,machInstCacheSize        # Must load before isolating
  163.     lw    t2,machDataCacheSize        # Must load before isolating
  164.     mfc0    t3,MACH_COP_0_STATUS_REG     # Save the status register.
  165.     mtc0    zero,MACH_COP_0_STATUS_REG    # Disable interrupts.
  166.     .set    noreorder
  167.     la    v0,1f
  168.     or    v0,VMMACH_PHYS_UNCACHED_START    # Run uncached.
  169.     j    v0            
  170.     nop
  171.  
  172.     /*
  173.      * flush text cache
  174.      */
  175. 1:    li    v0,MACH_SR_ISOL_CACHES|MACH_SR_SWAP_CACHES
  176.     mtc0    v0,MACH_COP_0_STATUS_REG    # Isolate and swap caches.
  177.     li    t0,VMMACH_PHYS_UNCACHED_START
  178.     subu    t0,t1
  179.     li    t1,VMMACH_PHYS_UNCACHED_START
  180.     la    v0,1f                # Run cached
  181.     j    v0
  182.     nop
  183.     .set    reorder
  184.  
  185. 1:    sb    zero,0(t0)
  186.     sb    zero,4(t0)
  187.     sb    zero,8(t0)
  188.     sb    zero,12(t0)
  189.     sb    zero,16(t0)
  190.     sb    zero,20(t0)
  191.     sb    zero,24(t0)
  192.     addu    t0,32
  193.     sb    zero,-4(t0)
  194.     bne    t0,t1,1b
  195.  
  196.     .set    noreorder
  197.     la    v0,1f
  198.     or    v0,VMMACH_PHYS_UNCACHED_START
  199.     j    v0                # Run uncached
  200.     nop
  201.  
  202.     /*
  203.      * flush data cache
  204.      */
  205. 1:    li    v0,MACH_SR_ISOL_CACHES|MACH_SR_SWAP_CACHES
  206.     mtc0    v0,MACH_COP_0_STATUS_REG    # Isolate and swap back caches
  207.     li    t0,VMMACH_PHYS_UNCACHED_START
  208.     subu    t0,t2
  209.     la    v0,1f
  210.     j    v0                # Back to cached mode
  211.     nop
  212.     .set    reorder
  213.  
  214. 1:    sb    zero,0(t0)
  215.     sb    zero,4(t0)
  216.     sb    zero,8(t0)
  217.     sb    zero,12(t0)
  218.     sb    zero,16(t0)
  219.     sb    zero,20(t0)
  220.     sb    zero,24(t0)
  221.     addu    t0,32
  222.     sb    zero,-4(t0)
  223.     bne    t0,t1,1b
  224.  
  225.     .set    noreorder
  226.     nop                    # Insure isolated stores 
  227.     nop                    #     out of pipe.
  228.     nop
  229.     mtc0    t3,MACH_COP_0_STATUS_REG    # Restore status reg.
  230.     nop                    # Insure cache unisolated.
  231.     nop
  232.     nop
  233.     nop
  234.     .set    reorder
  235.     j    ra
  236.  
  237. /*----------------------------------------------------------------------------
  238.  *
  239.  * MachCleanICache --
  240.  *
  241.  *    MachCleanICache(addr, len)
  242.  *
  243.  *    Flush i cache for range ofaddr to addr + len - 1.
  244.  *
  245.  * Results:
  246.  *         None.
  247.  *
  248.  * Side effects:
  249.  *    The contents of the cache is flushed.
  250.  *
  251.  *----------------------------------------------------------------------------
  252.  */
  253.     .globl MachCleanICache
  254. MachCleanICache:
  255.     lw    t1,machInstCacheSize
  256.     mfc0    t3,MACH_COP_0_STATUS_REG    # Save SR
  257.     mtc0    zero,MACH_COP_0_STATUS_REG    # Disable interrupts.
  258.  
  259.     .set    noreorder
  260.     la    v0,1f
  261.     or    v0,VMMACH_PHYS_UNCACHED_START    # Run uncached.
  262.     j    v0
  263.     nop
  264.  
  265. 1:    li    v0,MACH_SR_ISOL_CACHES|MACH_SR_SWAP_CACHES
  266.     mtc0    v0,MACH_COP_0_STATUS_REG
  267.     bltu    t1,a1,1f        # cache is smaller than region
  268.     nop
  269.     move    t1,a1
  270. 1:    addu    t1,a0            # ending address + 1
  271.     move    t0,a0
  272.     la    v0,1f            # run cached
  273.     j    v0
  274.     nop
  275.     .set    reorder
  276.  
  277. 1:    sb    zero,0(t0)
  278.     sb    zero,4(t0)
  279.     sb    zero,8(t0)
  280.     sb    zero,12(t0)
  281.     sb    zero,16(t0)
  282.     sb    zero,20(t0)
  283.     sb    zero,24(t0)
  284.     addu    t0,32
  285.     sb    zero,-4(t0)
  286.     bltu    t0,t1,1b
  287.  
  288.     .set    noreorder
  289.     la    v0,1f
  290.     or    v0,VMMACH_PHYS_UNCACHED_START
  291.     j    v0            # Run uncached
  292.     nop
  293.  
  294. 1:    nop                # insure isolated stores out of pipe
  295.     mtc0    zero,MACH_COP_0_STATUS_REG  # unisolate, unswap
  296.     nop                # keep pipeline clean
  297.     nop                # keep pipeline clean
  298.     nop                # keep pipeline clean
  299.     mtc0    t3,MACH_COP_0_STATUS_REG # enable interrupts
  300.     nop
  301.     j    ra            # return and run cached
  302.     nop
  303.     .set    reorder
  304.  
  305.     .globl MachFetchICache
  306. MachFetchICache:
  307.     mfc0    t3,MACH_COP_0_STATUS_REG    # Save SR
  308.     mtc0    zero,MACH_COP_0_STATUS_REG    # Disable interrupts.
  309.  
  310.     .set    noreorder
  311.     la    v0,1f
  312.     or    v0,VMMACH_PHYS_UNCACHED_START    # Run uncached.
  313.     j    v0
  314.     nop
  315.  
  316. 1:    li    v0,MACH_SR_ISOL_CACHES|MACH_SR_SWAP_CACHES
  317.     mtc0    v0,MACH_COP_0_STATUS_REG
  318.     la    v0,1f            # run cached
  319.     j    v0
  320.     nop
  321. 1:    ld    v0, 0(a0)
  322.     nop
  323.  
  324.     la    t0,1f
  325.     or    t0,VMMACH_PHYS_UNCACHED_START
  326.     j    t0            # Run uncached
  327.     nop
  328.  
  329. 1:    mtc0    zero, MACH_COP_0_STATUS_REG  # unisolate, unswap
  330.     nop                # keep pipeline clean
  331.     nop                # keep pipeline clean
  332.     nop                # keep pipeline clean
  333.     mtc0    t3,MACH_COP_0_STATUS_REG # enable interrupts
  334.     nop
  335.     j    ra            # return and run cached
  336.     nop
  337.     .set    reorder
  338.  
  339. /*----------------------------------------------------------------------------
  340.  *
  341.  * Mach_FlushCacheRange --
  342.  *
  343.  *    Mach_FlushCacheRange(addr, len)
  344.  *
  345.  *    Flush d cache for range ofaddr to addr + len - 1.
  346.  *
  347.  * Results:
  348.  *         None.
  349.  *
  350.  * Side effects:
  351.  *    The contents of the d cache is flushed.
  352.  *
  353.  *----------------------------------------------------------------------------
  354.  */
  355.     .globl Mach_FlushCacheRange
  356. Mach_FlushCacheRange:
  357.     lw    t1,machDataCacheSize
  358.     mfc0    t3,MACH_COP_0_STATUS_REG    # Save SR
  359.     mtc0    zero,MACH_COP_0_STATUS_REG    # Disable interrupts.
  360.  
  361.     .set    noreorder
  362.     la    v0,1f
  363.     or    v0,VMMACH_PHYS_UNCACHED_START    # Run uncached.
  364.     j    v0
  365.     nop
  366.  
  367. 1:    li    v0,MACH_SR_ISOL_CACHES    #isolate cache
  368.     mtc0    v0,MACH_COP_0_STATUS_REG
  369.     bltu    t1,a1,1f        # cache is smaller than region
  370.     nop
  371.     move    t1,a1
  372. 1:    addu    t1,a0            # ending address + 1
  373.     move    t0,a0
  374.     la    v0,1f            # run cached
  375.     j    v0
  376.     nop
  377.     .set    reorder
  378.  
  379. 1:    sb    zero,0(t0)
  380.     sb    zero,4(t0)
  381.     sb    zero,8(t0)
  382.     sb    zero,12(t0)
  383.     sb    zero,16(t0)
  384.     sb    zero,20(t0)
  385.     sb    zero,24(t0)
  386.     addu    t0,32
  387.     sb    zero,-4(t0)
  388.     bltu    t0,t1,1b
  389.  
  390.     .set    noreorder
  391.     la    v0,1f
  392.     or    v0,VMMACH_PHYS_UNCACHED_START
  393.     j    v0            # Run uncached
  394.     nop
  395.  
  396. 1:    nop                # insure isolated stores out of pipe
  397.     mtc0    zero,MACH_COP_0_STATUS_REG  # unisolate, unswap
  398.     nop                # keep pipeline clean
  399.     nop                # keep pipeline clean
  400.     nop                # keep pipeline clean
  401.     mtc0    t3,MACH_COP_0_STATUS_REG # enable interrupts
  402.     nop
  403.     j    ra            # return and run cached
  404.     nop
  405.     .set    reorder
  406.  
  407.  
  408.  
  409. /*----------------------------------------------------------------------------
  410.  *
  411.  * MachRunUserProc --
  412.  *
  413.  *    MachRunUserProc(pc, sp)
  414.  *        Address    pc;    * The program counter to execute at.
  415.  *        Address sp;    * The stack pointer to start with.
  416.  *
  417.  *    Start a process running in user mode.  We are called with interrupts
  418.  *    disabled.  
  419.  *
  420.  *
  421.  * Results:
  422.  *         None.
  423.  *
  424.  * Side effects:
  425.  *    The status register and stack pointer are modified.
  426.  *
  427.  *----------------------------------------------------------------------------
  428.  */
  429. LEAF(MachRunUserProc)
  430. .set noreorder
  431.     subu    sp, sp, STAND_FRAME_SIZE
  432.     sw        ra, STAND_RA_OFFSET(sp)
  433.     sw        a0, STAND_FRAME_SIZE(sp)
  434.     sw        a1, STAND_FRAME_SIZE + 4(sp)
  435.     .mask    0x80000000, -4
  436.     li        t0, (MACH_KERN_INT_MASK|MACH_SR_KU_PREV|MACH_SR_INT_ENA_PREV)
  437.     mtc0    t0, MACH_COP_0_STATUS_REG
  438.     lw        k0, machCurStatePtr
  439.     addu    k1, a0, zero
  440. .set noat
  441.     RESTORE_REGS(k0, MACH_TRAP_REGS_OFFSET)
  442. .set at
  443.  
  444.     j        k1
  445.     rfe
  446. .set reorder
  447. END(MachRunUserProc)
  448.  
  449. /*----------------------------------------------------------------------------
  450.  *
  451.  * MachException --
  452.  *
  453.  *    Handle a general exception.
  454.  *
  455.  *
  456.  * Results:
  457.  *         None.
  458.  *
  459.  * Side effects:
  460.  *    None.
  461.  *
  462.  *----------------------------------------------------------------------------
  463.  */
  464.     .globl MachException
  465. MachException:
  466. .set noat
  467. /*
  468.  * Find out what mode we came from.
  469.  */
  470.     mfc0    k0, MACH_COP_0_STATUS_REG
  471.     and        k0, k0, MACH_SR_KU_PREV
  472.     bne        k0, zero, 1f
  473.     j        MachKernException
  474. 1:  j        MachUserException
  475. .set at
  476.     .globl MachEndException
  477. MachEndException:
  478.  
  479. /*----------------------------------------------------------------------------
  480.  *
  481.  * MachKernException --
  482.  *
  483.  *    Handle an exception from kernel mode.
  484.  *
  485.  * Results:
  486.  *         None.
  487.  *
  488.  * Side effects:
  489.  *    None.
  490.  *
  491.  *----------------------------------------------------------------------------
  492.  */
  493.     .globl MachKernException
  494. MachKernException:
  495. /*
  496.  * Determine the type of fault and jump to the appropriate routine.
  497.  */
  498. .set noreorder
  499. .set noat
  500.     mfc0    k0, MACH_COP_0_CAUSE_REG    # Get the cause register value.
  501.     la        k1, machKernExcTable        # Load base of the func table.
  502.     and        k0, k0, MACH_CR_EXC_CODE    # Mask out the cause bits. 
  503.     addu    k0, k0, k1            # Get the address of the
  504.                         #    function entry.  Note that
  505.                         #    the cause is already 
  506.                         #    shifted left by 2 bits so
  507.                         #    we don't have to shift.
  508.     lw        k0, 0(k0)            # Get the function address
  509.     nop
  510.     j        k0                # Jump to the function.
  511.     nop
  512. .set at
  513. .set reorder
  514.  
  515.  
  516. /*----------------------------------------------------------------------------
  517.  *
  518.  * Mach_KernGenException --
  519.  *
  520.  *    Handle an exception from kernel mode.
  521.  *
  522.  * Results:
  523.  *         None.
  524.  *
  525.  * Side effects:
  526.  *    None.
  527.  *
  528.  *----------------------------------------------------------------------------
  529.  */
  530.  
  531. /*
  532.  * The kernel exception stack contains 28 saved general registers, the
  533.  * status register and the cause register and the multiply lo and high 
  534.  * registers.  In addition we need to set
  535.  * this up for linkage conventions.
  536.  *
  537.  * Kgdb depends on the following definitions.  If you change them you
  538.  * must modify the routine frame_saved_pc in kgdb.mips accordingly.
  539.  */
  540. #define    KERN_EXC_FRAME_SIZE    (STAND_FRAME_SIZE + 8 + SAVED_REG_SIZE + 8)
  541. #define KERN_SR_OFFSET        (STAND_FRAME_SIZE)
  542. #define CAUSE_OFFSET        (STAND_FRAME_SIZE + 4)
  543. #define SAVED_REG_OFFSET    (STAND_FRAME_SIZE + 8)
  544. #define KERN_MULT_LO_OFFSET    (STAND_FRAME_SIZE + 8 + SAVED_REG_SIZE)
  545. #define KERN_MULT_HI_OFFSET    (STAND_FRAME_SIZE + 8 + SAVED_REG_SIZE + 4)
  546.  
  547. NON_LEAF(Mach_KernGenException,KERN_EXC_FRAME_SIZE,ra)
  548. .set noreorder
  549. .set noat
  550.     subu    sp, sp, KERN_EXC_FRAME_SIZE
  551. /*
  552.  * Save kernel registers onto the stack.
  553.  */
  554.     SAVE_KERNEL_REGS(SAVED_REG_OFFSET)
  555.     mflo    t0
  556.     sw        t0, KERN_MULT_LO_OFFSET(sp)
  557.     mfhi    t0
  558.     sw        t0, KERN_MULT_HI_OFFSET(sp)
  559. /*
  560.  * Save the rest of the state.
  561.  */
  562.     mfc0    k0, MACH_COP_0_EXC_PC
  563.     mfc0    k1, MACH_COP_0_STATUS_REG
  564.     sw        k0, STAND_RA_OFFSET(sp)
  565.     .mask    0x80000000, (STAND_RA_OFFSET - KERN_EXC_FRAME_SIZE)
  566.     sw        k1, KERN_SR_OFFSET(sp)
  567.     mfc0    k0, MACH_COP_0_CAUSE_REG
  568.     nop
  569.     sw        k0, CAUSE_OFFSET(sp)
  570.  
  571. /*
  572.  * Call the exception handler.
  573.  */
  574.     mfc0    a0, MACH_COP_0_STATUS_REG    # First arg is the status reg.
  575.     mfc0    a1, MACH_COP_0_CAUSE_REG    # Second arg is the cause reg.
  576.     mfc0    a2, MACH_COP_0_BAD_VADDR    # Third arg is the fault addr.
  577.     mfc0    a3, MACH_COP_0_EXC_PC        # Fourth arg is the pc.
  578.  
  579. /*
  580.  * Don't disable interrupts from the memory system, unless there is
  581.  * a memory system interrupt pending.
  582.  */
  583.     and        t0, a0, MACH_INT_MASK_3
  584.     bne        zero, t0, 10f
  585.     nop
  586.     mfc0    t0, MACH_COP_0_STATUS_REG
  587.     and        t0, t0, ~MACH_KERN_INT_MASK
  588.     or        t0, t0, MACH_INT_MASK_3 | MACH_SR_INT_ENA_CUR
  589.     mtc0    t0, MACH_COP_0_STATUS_REG
  590.     nop
  591.     nop
  592. 10:
  593.     jal        MachKernelExceptionHandler
  594.     nop
  595.     mtc0    zero, MACH_COP_0_STATUS_REG    # Disable interrupts
  596.     nop
  597. /*
  598.  * Check error code.
  599.  */
  600.     li        t0, MACH_OK
  601.     li        t1, MACH_USER_ERROR
  602.     beq        v0, t0, 9f
  603.     nop
  604.     beq        v0, t1, 8f
  605.     nop
  606.  
  607. /*
  608.  * We got a kernel error.  Save the special registers that we saved on 
  609.  * the stack into the debug state struct.
  610.  */
  611.     lw        k0, machDebugStatePtr
  612.     lw        k1, KERN_SR_OFFSET(sp)
  613.     nop
  614.     sw        k1, MACH_DEBUG_STATUS_REG_OFFSET(k0)
  615.     lw        k1, STAND_RA_OFFSET(sp)
  616.     nop
  617.     sw        k1, MACH_DEBUG_EXC_PC_OFFSET(k0)
  618.     lw        k1, CAUSE_OFFSET(sp)
  619.     nop
  620.     sw        k1, MACH_DEBUG_CAUSE_REG_OFFSET(k0)
  621.  
  622. /*
  623.  * Restore kernel registers and pop the stack.
  624.  */
  625.     lw        t0, KERN_MULT_LO_OFFSET(sp)
  626.     lw        t1, KERN_MULT_HI_OFFSET(sp)
  627.     mtlo    t0
  628.     mthi    t1
  629.     RESTORE_KERNEL_REGS(SAVED_REG_OFFSET)
  630.     addu    sp, sp, KERN_EXC_FRAME_SIZE
  631.  
  632. /*
  633.  * Save the general registers into the debug state struct.
  634.  */
  635.     SAVE_REGS(k0, MACH_DEBUG_REGS_OFFSET)
  636.     sw        gp, MACH_DEBUG_REGS_OFFSET +  (4 * GP)(k0)
  637.     sw        sp, MACH_DEBUG_REGS_OFFSET +  (4 * SP)(k0)
  638.     mflo    t0
  639.     sw        t0, MACH_DEBUG_MULT_LO_OFFSET(k0)
  640.     mfhi    t0
  641.     sw        t0, MACH_DEBUG_MULT_HI_OFFSET(k0)
  642.  
  643. /*
  644.  * Now save the rest of the special registers.
  645.  */
  646.     mfc0    t0, MACH_COP_0_TLB_INDEX
  647.     nop
  648.     sw        t0, MACH_DEBUG_TLB_INDEX_OFFSET(k0)
  649.     mfc0    t0, MACH_COP_0_TLB_RANDOM
  650.     nop
  651.     sw        t0, MACH_DEBUG_TLB_RANDOM_OFFSET(k0)
  652.     mfc0    t0, MACH_COP_0_TLB_LOW
  653.     nop
  654.     sw        t0, MACH_DEBUG_TLB_LOW_OFFSET(k0)
  655.     mfc0    t0, MACH_COP_0_TLB_CONTEXT
  656.     nop
  657.     sw        t0, MACH_DEBUG_TLB_CONTEXT_OFFSET(k0)
  658.     mfc0    t0, MACH_COP_0_BAD_VADDR
  659.     nop
  660.     sw        t0, MACH_DEBUG_BAD_VADDR_OFFSET(k0)
  661.     mfc0    t0, MACH_COP_0_TLB_HI
  662.     nop
  663.     sw        t0, MACH_DEBUG_TLB_HI_OFFSET(k0)
  664. /*
  665.  * Save the floating point state.
  666.  */
  667.  
  668. .set at
  669.     mfc0    t0, MACH_COP_0_STATUS_REG
  670.     nop
  671.     or        t0, t0, MACH_SR_COP_1_BIT
  672.     mtc0    t0, MACH_COP_0_STATUS_REG
  673.     nop
  674.     nop
  675.     cfc1    t1, MACH_FPC_CSR
  676.     nop
  677.     sw        t1, MACH_DEBUG_FPC_CSR_REG_OFFSET(k0)
  678.  
  679. #define SAVE_DEBUG_CP1_REG(reg) \
  680.     swc1    $f/**/reg, MACH_DEBUG_FP_REGS_OFFSET+reg*4(k0)
  681.  
  682.     SAVE_DEBUG_CP1_REG(0);  SAVE_DEBUG_CP1_REG(1);  SAVE_DEBUG_CP1_REG(2)
  683.     SAVE_DEBUG_CP1_REG(3);  SAVE_DEBUG_CP1_REG(4);  SAVE_DEBUG_CP1_REG(5)
  684.     SAVE_DEBUG_CP1_REG(6);  SAVE_DEBUG_CP1_REG(7);  SAVE_DEBUG_CP1_REG(8)
  685.     SAVE_DEBUG_CP1_REG(9);  SAVE_DEBUG_CP1_REG(10); SAVE_DEBUG_CP1_REG(11)
  686.     SAVE_DEBUG_CP1_REG(12); SAVE_DEBUG_CP1_REG(13); SAVE_DEBUG_CP1_REG(14)
  687.     SAVE_DEBUG_CP1_REG(15); SAVE_DEBUG_CP1_REG(16); SAVE_DEBUG_CP1_REG(17)
  688.     SAVE_DEBUG_CP1_REG(18); SAVE_DEBUG_CP1_REG(19); SAVE_DEBUG_CP1_REG(20)
  689.     SAVE_DEBUG_CP1_REG(21); SAVE_DEBUG_CP1_REG(22); SAVE_DEBUG_CP1_REG(23)
  690.     SAVE_DEBUG_CP1_REG(24); SAVE_DEBUG_CP1_REG(25); SAVE_DEBUG_CP1_REG(26)
  691.     SAVE_DEBUG_CP1_REG(27); SAVE_DEBUG_CP1_REG(28); SAVE_DEBUG_CP1_REG(29)
  692.     SAVE_DEBUG_CP1_REG(30); SAVE_DEBUG_CP1_REG(31)
  693. .set noat
  694.  
  695. /*
  696.  * Switch to the debuggers stack and call the debugger.  The debuggers
  697.  * stack starts at the base of the first kernel stack.
  698.  */
  699.     li        sp, MACH_STACK_BOTTOM - STAND_FRAME_SIZE
  700.     jal        Dbg_Main
  701.     nop
  702. /*
  703.  * The debugger returns the PC to continue at.
  704.  */
  705.     addu    k1, v0, 0
  706.     lw        k0, machDebugStatePtr
  707.     nop
  708.  
  709.     lw        t0, MACH_DEBUG_MULT_LO_OFFSET(k0)
  710.     lw        t1, MACH_DEBUG_MULT_HI_OFFSET(k0)
  711.     mtlo    t0
  712.     mthi    t1
  713.     RESTORE_REGS(k0, MACH_DEBUG_REGS_OFFSET)
  714.     lw        k0, MACH_DEBUG_STATUS_REG_OFFSET(k0)
  715.     nop
  716.     mtc0    k0, MACH_COP_0_STATUS_REG    
  717.     nop
  718.     j        k1
  719.     rfe
  720.  
  721. 8:
  722. /*
  723.  * We got an error on a cross address space copy.  All we have to do is
  724.  * restore the stack pointer and the status register, set the return value
  725.  * register and return.
  726.  */
  727.     lw        t0, KERN_MULT_LO_OFFSET(sp)
  728.     lw        t1, KERN_MULT_HI_OFFSET(sp)
  729.     mtlo    t0
  730.     mthi    t1
  731.     RESTORE_KERNEL_REGS(SAVED_REG_OFFSET)
  732.     lui        v0, 0x2                # v0 <= SYS_ARG_NO_ACCESS
  733.     lw        k0, KERN_SR_OFFSET(sp)        # Get the saved sp.
  734.     addu    sp, sp, KERN_EXC_FRAME_SIZE    # Clear off the stack.
  735.     mtc0    k0, MACH_COP_0_STATUS_REG    # Restore the status register.
  736.     nop
  737.     j        ra                # Now return to the caller
  738.     rfe                        #   who caused the error.
  739.  
  740.  
  741. 9:
  742. /*
  743.  * Restore registers and return from the exception.
  744.  */
  745.     lw        t0, KERN_MULT_LO_OFFSET(sp)
  746.     lw        t1, KERN_MULT_HI_OFFSET(sp)
  747.     mtlo    t0
  748.     mthi    t1
  749.     RESTORE_KERNEL_REGS(SAVED_REG_OFFSET)
  750.  
  751.     lw        k0, KERN_SR_OFFSET(sp)
  752.     lw        k1, STAND_RA_OFFSET(sp)
  753.     addu    sp, sp, KERN_EXC_FRAME_SIZE
  754.     mtc0    k0, MACH_COP_0_STATUS_REG    # Restore the SR
  755.     nop
  756.     j        k1                # Now return from the
  757.     rfe                        #    exception.
  758. END(Mach_KernGenException)
  759.     .set at
  760.     .set reorder
  761.  
  762. /*----------------------------------------------------------------------------
  763.  *
  764.  * MachUserException --
  765.  *
  766.  *    Handle an exception from user mode.
  767.  *
  768.  * Results:
  769.  *         None.
  770.  *
  771.  * Side effects:
  772.  *    None.
  773.  *
  774.  *----------------------------------------------------------------------------
  775.  */
  776.     .globl MachUserException
  777. MachUserException:
  778. .set noreorder
  779. .set noat
  780.     mfc0    k0, MACH_COP_0_CAUSE_REG    # Get the cause register value.
  781.     la        k1, machUserExcTable        # Load base of the func table.
  782.     and        k0, k0, MACH_CR_EXC_CODE    # Mask out the cause bits. 
  783.     addu    k0, k0, k1            # Get the address of the
  784.                         #    function entry.  Note that
  785.                         #    the cause is already 
  786.                         #    shifted left by 2 bits so
  787.                         #    we don't have to shift.
  788.     lw        k0, 0(k0)            # Get the function address
  789.     nop
  790.     j        k0                # Jump to the function.
  791.     nop
  792. .set at
  793. .set reorder
  794.  
  795. /*----------------------------------------------------------------------------
  796.  *
  797.  * Mach_UserGenException --
  798.  *
  799.  *    Handle an exception from user mode.
  800.  *
  801.  * Results:
  802.  *         None.
  803.  *
  804.  * Side effects:
  805.  *    None.
  806.  *
  807.  *----------------------------------------------------------------------------
  808.  */
  809. /*
  810.  * The user exception stack contains the status register and the exception
  811.  * PC.
  812.  */
  813. #define    USER_EXC_FRAME_SIZE    (4 + STAND_FRAME_SIZE)
  814. #define USER_SR_OFFSET        (STAND_RA_OFFSET + 4)
  815.  
  816. NON_LEAF(Mach_UserGenException,USER_EXC_FRAME_SIZE,ra)
  817. .set noreorder
  818. .set noat
  819. /*
  820.  * First of all switch over to the kernel gp.
  821.  */
  822.     addu    k1, gp, zero
  823.     la        gp, _gp
  824.     lw        k0, machCurStatePtr
  825.     nop
  826. /*
  827.  * Save all registers.
  828.  */
  829.     sw        sp, MACH_TRAP_REGS_OFFSET + (SP * 4)(k0)
  830.     sw        k1, MACH_TRAP_REGS_OFFSET + (GP * 4)(k0)
  831.     SAVE_REGS(k0, MACH_TRAP_REGS_OFFSET)
  832.     mflo    t0
  833.     sw        t0, MACH_TRAP_MULT_LO_OFFSET(k0)
  834.     mfhi    t0
  835.     sw        t0, MACH_TRAP_MULT_HI_OFFSET(k0)
  836. .set at
  837.  
  838. /*
  839.  * Change to the kernel's stack.
  840.  */
  841.     lw        sp, MACH_KERN_STACK_END_OFFSET(k0)
  842. /*
  843.  * Set up the stack frame.
  844.  */
  845.     mfc0    a3, MACH_COP_0_EXC_PC        # The fourth arg is the PC
  846.     subu    sp, sp, USER_EXC_FRAME_SIZE
  847.     sw        a3, STAND_RA_OFFSET(sp)
  848.     sw        a3, MACH_USER_PC_OFFSET(k0)
  849.     .mask    0x80000000, (STAND_RA_OFFSET - USER_EXC_FRAME_SIZE)
  850.  
  851.     mfc0    a0, MACH_COP_0_STATUS_REG    # First arg is the status reg.
  852.     nop
  853.     and        k1, a0, ~MACH_SR_COP_1_BIT    # Turn off the FPU.
  854.     mtc0    k1, MACH_COP_0_STATUS_REG
  855.     sw        k1, USER_SR_OFFSET(sp)
  856.  
  857. /*
  858.  * Call the handler.
  859.  */
  860.     mfc0    a1, MACH_COP_0_CAUSE_REG    # Second arg is the cause reg.
  861.     mfc0    a2, MACH_COP_0_BAD_VADDR    # Third arg is the fault addr
  862.     jal        MachUserExceptionHandler
  863.     nop
  864.  
  865. /*
  866.  * Restore user registers and return.  Interrupts are already disabled
  867.  * when MachUserExceptionHandler returns.
  868.  */
  869.     lw        k0, USER_SR_OFFSET(sp)
  870.     beq        v0, zero, 1f            # See if we are supposed to
  871.     nop                        #   to turn on the FPU.
  872.     or        k0, k0, MACH_SR_COP_1_BIT
  873. 1:
  874.     mtc0    k0, MACH_COP_0_STATUS_REG
  875.     lw        k0, machCurStatePtr
  876.     nop
  877. .set noat
  878.     lw        t0, MACH_TRAP_MULT_LO_OFFSET(k0)
  879.     lw        t1, MACH_TRAP_MULT_HI_OFFSET(k0)
  880.     mtlo    t0
  881.     mthi    t1
  882.     RESTORE_REGS(k0, MACH_TRAP_REGS_OFFSET)
  883.     lw        k1, MACH_USER_PC_OFFSET(k0)
  884.     nop
  885.     j        k1
  886.     rfe
  887. END(Mach_UserGenException)
  888. .set at
  889. .set reorder
  890.  
  891.  
  892. /*----------------------------------------------------------------------------
  893.  *
  894.  * Mach_EnableIntr --
  895.  *
  896.  *    Enable interrupts.
  897.  *
  898.  * Results:
  899.  *         None.
  900.  *
  901.  * Side effects:
  902.  *    Interrupts enabled.
  903.  *
  904.  *----------------------------------------------------------------------------
  905.  */
  906. LEAF(Mach_EnableIntr)
  907. .set noreorder
  908.     mfc0    t0, MACH_COP_0_STATUS_REG
  909.     nop
  910.     or        t0, t0, MACH_KERN_INT_MASK | MACH_SR_INT_ENA_CUR
  911.     mtc0    t0, MACH_COP_0_STATUS_REG
  912.     nop
  913.     j        ra
  914.     nop
  915. .set reorder
  916. END(Mach_EnableIntr)
  917.  
  918. /*----------------------------------------------------------------------------
  919.  *
  920.  * Mach_DisableIntr --
  921.  *
  922.  *    Disable Interrupts.
  923.  *
  924.  * Results:
  925.  *         None.
  926.  *
  927.  * Side effects:
  928.  *    Interrupts disabled.
  929.  *
  930.  *----------------------------------------------------------------------------
  931.  */
  932. LEAF(Mach_DisableIntr)
  933. .set noreorder
  934.     mfc0    t0, MACH_COP_0_STATUS_REG
  935.     nop
  936.     and        t0, t0, ~(MACH_SR_INT_ENA_CUR | MACH_KERN_INT_MASK)
  937.     or        t0, t0, MACH_INT_MASK_3 | MACH_SR_INT_ENA_CUR
  938.     mtc0    t0, MACH_COP_0_STATUS_REG
  939.     nop
  940.     j        ra
  941.     nop
  942. .set reorder
  943. END(Mach_DisableIntr)
  944.  
  945. /*----------------------------------------------------------------------------
  946.  *
  947.  * Mach_ContextSwitch --
  948.  *
  949.  *    Mach_ContextSwitch(fromProcPtr, toProcPtr)
  950.  *
  951.  *    Perform a context switch.
  952.  *
  953.  * Results:
  954.  *         None.
  955.  *
  956.  * Side effects:
  957.  *    The current process's state is saved into its machine specific
  958.  *    process table entry and new state is loaded for the switched to
  959.  *    process.  
  960.  *
  961.  *----------------------------------------------------------------------------
  962.  */
  963. .set noreorder
  964.  
  965. NON_LEAF(Mach_ContextSwitch,STAND_FRAME_SIZE,ra)
  966.     subu    sp, sp, STAND_FRAME_SIZE
  967.     sw        ra, STAND_RA_OFFSET(sp)
  968.     sw        a0, STAND_FRAME_SIZE(sp)
  969.     sw        a1, STAND_FRAME_SIZE + 4(sp)
  970.     .mask    0x80000000, -4
  971. /*
  972.  * Set up this processes context.
  973.  */
  974.     addu    a0, a1, zero
  975.     jal        VmMach_SetupContext
  976.     nop
  977. /*
  978.  * Restore saved register values.
  979.  */
  980.     lw        ra, STAND_RA_OFFSET(sp)
  981.     lw        a0, STAND_FRAME_SIZE(sp)
  982.     lw        a1, STAND_FRAME_SIZE + 4(sp)
  983. /*
  984.  * Push the magic number and the status register onto the stack.
  985.  */
  986.     subu    sp, sp, 8
  987.     li        t0, MAGIC
  988.     sw        t0, 0(sp)
  989.     mfc0    t0, MACH_COP_0_STATUS_REG # Save the status reg.
  990.     nop
  991.     sw        t0, 4(sp)
  992.  
  993. /*
  994.  * Save the state of the current process.  We only have to save the saved
  995.  * register registers (s0 through s8) and the stack pointer.
  996.  */
  997.     lw        t0, machCurStatePtr
  998.     nop
  999.     addu    t0, t0, MACH_SWITCH_REGS_OFFSET
  1000.     sw        a0, A0 * 4(t0)
  1001.     sw        s0, S0 * 4(t0)
  1002.     sw        s1, S1 * 4(t0)
  1003.     sw        s2, S2 * 4(t0)
  1004.     sw        s3, S3 * 4(t0)
  1005.     sw        s4, S4 * 4(t0)
  1006.     sw        s5, S5 * 4(t0)
  1007.     sw        s6, S6 * 4(t0)
  1008.     sw        s7, S7 * 4(t0)
  1009.     sw        s8, S8 * 4(t0)
  1010.     sw        ra, RA * 4(t0)
  1011.     sw        sp, SP * 4(t0)
  1012.     .globl Mach_SwitchPoint
  1013. Mach_SwitchPoint:
  1014.  
  1015. /*
  1016.  * Restore the registers for the new process.
  1017.  */
  1018.     lw        t0, machStatePtrOffset
  1019.     nop
  1020.     addu    t0, a1, t0
  1021.     lw        t0, 0(t0)
  1022.     nop
  1023.     sw        t0, machCurStatePtr
  1024.     addu    t1, t0, MACH_SWITCH_REGS_OFFSET
  1025.     lw        a0, A0 * 4(t1)
  1026.     lw        s0, S0 * 4(t1)
  1027.     lw        s1, S1 * 4(t1)
  1028.     lw        s2, S2 * 4(t1)
  1029.     lw        s3, S3 * 4(t1)
  1030.     lw        s4, S4 * 4(t1)
  1031.     lw        s5, S5 * 4(t1)
  1032.     lw        s6, S6 * 4(t1)
  1033.     lw        s7, S7 * 4(t1)
  1034.     lw        s8, S8 * 4(t1)
  1035.     lw        ra, RA * 4(t1)
  1036.     lw        sp, SP * 4(t1)
  1037. /*
  1038.  * Set up the maximum stack addr for the debugger.
  1039.  */
  1040.     lw        t1, MACH_KERN_STACK_END_OFFSET(t0)
  1041.     nop
  1042.     sw        t1, dbgMaxStackAddr
  1043.  
  1044. /*
  1045.  * Wire down the current process's stack in the TLB.  This
  1046.  * code depends implicitly upon MACH_KERN_STACK_PAGES.
  1047.  */
  1048.     mfc0    t1, VMMACH_TLB_HI
  1049.  
  1050. /*
  1051.  * Map the first entry.
  1052.  */
  1053.     lw        t2, MACH_TLB_HIGH_ENTRY_OFFSET(t0)
  1054.     lw        t3, MACH_TLB_LOW_ENTRY_1_OFFSET(t0)
  1055.     li        t4, MACH_STACK_TLB_INDEX_1
  1056.     mtc0    t2, VMMACH_TLB_HI
  1057.     mtc0    t3, VMMACH_TLB_LOW
  1058.     mtc0    t4, VMMACH_TLB_INDEX
  1059.     nop
  1060.     tlbwi
  1061.  
  1062. /*
  1063.  * Map the second entry.
  1064.  */
  1065.     addu    t2, t2, 1 << VMMACH_TLB_VIRT_PAGE_SHIFT
  1066.     lw        t3, MACH_TLB_LOW_ENTRY_2_OFFSET(t0)
  1067.     li        t4, MACH_STACK_TLB_INDEX_2
  1068.     mtc0    t2, VMMACH_TLB_HI
  1069.     mtc0    t3, VMMACH_TLB_LOW
  1070.     mtc0    t4, VMMACH_TLB_INDEX
  1071.     nop
  1072.     tlbwi
  1073.  
  1074. /*
  1075.  * Map the third entry.
  1076.  */
  1077.     addu    t2, t2, 1 << VMMACH_TLB_VIRT_PAGE_SHIFT
  1078.     lw        t3, MACH_TLB_LOW_ENTRY_3_OFFSET(t0)
  1079.     li        t4, MACH_STACK_TLB_INDEX_3
  1080.     mtc0    t2, VMMACH_TLB_HI
  1081.     mtc0    t3, VMMACH_TLB_LOW
  1082.     mtc0    t4, VMMACH_TLB_INDEX
  1083.     nop
  1084.     tlbwi
  1085.  
  1086.     mtc0    t1, VMMACH_TLB_HI
  1087.  
  1088. /*
  1089.  * Verify the magic number on the stack.
  1090.  */
  1091.     lw        t0, 0(sp)
  1092.     li        t1, MAGIC
  1093.     beq        t0, t1, 1f
  1094.     nop
  1095.     break    0
  1096.  
  1097. /*
  1098.  * Restore the status register and pop the stack.
  1099.  */
  1100. 1:
  1101.     lw        t0, 4(sp)
  1102.     nop
  1103.     mtc0    t0, MACH_COP_0_STATUS_REG
  1104.     addu    sp, sp, STAND_FRAME_SIZE + 8
  1105. /*
  1106.  * Return 
  1107.  */
  1108.     j        ra
  1109.     nop
  1110.  
  1111. END(Mach_ContextSwitch)
  1112. .set reorder
  1113.  
  1114. /*----------------------------------------------------------------------------
  1115.  *
  1116.  * Mach_GetPC --
  1117.  *
  1118.  *    Return the caller's PC.
  1119.  *
  1120.  * Results:
  1121.  *         The PC of the caller.
  1122.  *
  1123.  * Side effects:
  1124.  *    None.
  1125.  *
  1126.  *----------------------------------------------------------------------------
  1127.  */
  1128.     .globl Mach_GetPC
  1129. Mach_GetPC:
  1130.     addu    v0, ra, zero
  1131.     j        ra
  1132.  
  1133. /*----------------------------------------------------------------------------
  1134.  *
  1135.  * Mach_GetCallerPC --
  1136.  *
  1137.  *    Return the caller's caller's PC.
  1138.  *
  1139.  * Results:
  1140.  *         I have no idea how to do this, so return 0 for now.
  1141.  *
  1142.  * Side effects:
  1143.  *    None.
  1144.  *
  1145.  *----------------------------------------------------------------------------
  1146.  */
  1147.     .globl Mach_GetCallerPC
  1148. Mach_GetCallerPC:
  1149.     addu    v0, zero, zero
  1150.     j        ra
  1151.  
  1152. /*----------------------------------------------------------------------------
  1153.  *
  1154.  * Mach_TestAndSet --
  1155.  *
  1156.  *    Mach_TestAndSet(intPtr)
  1157.  *
  1158.  *    Return the caller's caller's PC.
  1159.  *
  1160.  * Results:
  1161.  *         0 for now.
  1162.  *
  1163.  * Side effects:
  1164.  *    None.
  1165.  *
  1166.  *----------------------------------------------------------------------------
  1167.  */
  1168. LEAF(Mach_TestAndSet)
  1169.     mfc0    t0, MACH_COP_0_STATUS_REG
  1170.     mtc0    zero, MACH_COP_0_STATUS_REG    # Disable interrupts
  1171.     lw        v0, 0(a0)            # Read out old value
  1172.     li        t1, 1
  1173.     sw        t1, 0(a0)            # Set value.
  1174.     mtc0    t0, MACH_COP_0_STATUS_REG    # Restore interrupts.
  1175.     j        ra
  1176. END(Mach_TestAndSet)
  1177.  
  1178. /*----------------------------------------------------------------------------
  1179.  *
  1180.  * Mach_EmptyWriteBuffer --
  1181.  *
  1182.  *    Mach_EmptyWriteBuffer()
  1183.  *
  1184.  *    Return when the write buffer is empty.
  1185.  *
  1186.  * Results:
  1187.  *         None.
  1188.  *
  1189.  * Side effects:
  1190.  *    None.
  1191.  *
  1192.  *----------------------------------------------------------------------------
  1193.  */
  1194. LEAF(Mach_EmptyWriteBuffer)
  1195.     nop
  1196.     nop
  1197.     nop
  1198.     nop
  1199. 1:    bc0f    1b
  1200.     j    ra
  1201. END(Mach_EmptyWriteBuffer)
  1202.  
  1203. #define SAVE_CP1_REG(reg) \
  1204.     swc1    $f/**/reg, MACH_FP_REGS_OFFSET+reg*4(a0)
  1205.  
  1206. #define REST_CP1_REG(reg) \
  1207.     lwc1    $f/**/reg, MACH_FP_REGS_OFFSET+reg*4(a1)
  1208.  
  1209. /*----------------------------------------------------------------------------
  1210.  *
  1211.  * MachSwitchFPState --
  1212.  *
  1213.  *    MachSwitchFPState(fromFPStatePtr, toFPStatePtr)
  1214.  *
  1215.  *    Save the current state into fromFPStatePtrs state and restore it
  1216.  *    from toFPStatePtr.
  1217.  *
  1218.  * Results:
  1219.  *         None.
  1220.  *
  1221.  * Side effects:
  1222.  *    None.
  1223.  *
  1224.  *----------------------------------------------------------------------------
  1225.  */
  1226. LEAF(MachSwitchFPState)
  1227.     subu    sp, sp, STAND_FRAME_SIZE
  1228.     sw    ra, STAND_RA_OFFSET(sp)
  1229.     .mask    0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
  1230.  
  1231.     mfc0    t1, MACH_COP_0_STATUS_REG    # Disable interrupts and
  1232.     li    t0, MACH_SR_COP_1_BIT        #    enable the coprocessor
  1233.     mtc0    t0, MACH_COP_0_STATUS_REG
  1234.  
  1235.     addu    t0, a0, 1    # If fromFPStatePtr is NIL then it will equal
  1236.     beq    t0, zero, 1f    #    zero if we add one to it.
  1237.  
  1238. .set noreorder
  1239. /*
  1240.  * First read out the status register to make sure that all FP operations
  1241.  * have completed.
  1242.  */
  1243.     cfc1    t0, MACH_FPC_CSR
  1244.     nop
  1245.     sw    t0, MACH_FP_SR_OFFSET(a0)
  1246. /* 
  1247.  * Save the floating point registers.
  1248.  */
  1249.     SAVE_CP1_REG(0); SAVE_CP1_REG(1); SAVE_CP1_REG(2); SAVE_CP1_REG(3)
  1250.     SAVE_CP1_REG(4); SAVE_CP1_REG(5); SAVE_CP1_REG(6); SAVE_CP1_REG(7)
  1251.     SAVE_CP1_REG(8); SAVE_CP1_REG(9); SAVE_CP1_REG(10); SAVE_CP1_REG(11)
  1252.     SAVE_CP1_REG(12); SAVE_CP1_REG(13); SAVE_CP1_REG(14); SAVE_CP1_REG(15)
  1253.     SAVE_CP1_REG(16); SAVE_CP1_REG(17); SAVE_CP1_REG(18); SAVE_CP1_REG(19)
  1254.     SAVE_CP1_REG(20); SAVE_CP1_REG(21); SAVE_CP1_REG(22); SAVE_CP1_REG(23)
  1255.     SAVE_CP1_REG(24); SAVE_CP1_REG(25); SAVE_CP1_REG(26); SAVE_CP1_REG(27)
  1256.     SAVE_CP1_REG(28); SAVE_CP1_REG(29); SAVE_CP1_REG(30); SAVE_CP1_REG(31)
  1257.  
  1258. 1:    
  1259. /*
  1260.  * Restore the floating point registers.
  1261.  */
  1262.     REST_CP1_REG(0); REST_CP1_REG(1); REST_CP1_REG(2); REST_CP1_REG(3)
  1263.     REST_CP1_REG(4); REST_CP1_REG(5); REST_CP1_REG(6); REST_CP1_REG(7)
  1264.     REST_CP1_REG(8); REST_CP1_REG(9); REST_CP1_REG(10); REST_CP1_REG(11)
  1265.     REST_CP1_REG(12); REST_CP1_REG(13); REST_CP1_REG(14); REST_CP1_REG(15)
  1266.     REST_CP1_REG(16); REST_CP1_REG(17); REST_CP1_REG(18); REST_CP1_REG(19)
  1267.     REST_CP1_REG(20); REST_CP1_REG(21); REST_CP1_REG(22); REST_CP1_REG(23)
  1268.     REST_CP1_REG(24); REST_CP1_REG(25); REST_CP1_REG(26); REST_CP1_REG(27)
  1269.     REST_CP1_REG(28); REST_CP1_REG(29); REST_CP1_REG(30); REST_CP1_REG(31)
  1270.  
  1271.     lw    t0, MACH_FP_SR_OFFSET(a1)
  1272.     nop
  1273.     and    t0, t0, ~MACH_FPC_EXCEPTION_BITS
  1274.     ctc1    t0, MACH_FPC_CSR
  1275.     nop
  1276.     mtc0    t1, MACH_COP_0_STATUS_REG    # Restore the status register.
  1277.  
  1278.     addu    sp, sp, STAND_FRAME_SIZE
  1279.  
  1280.     j    ra
  1281.     nop
  1282.  
  1283. .set reorder
  1284. END(MachSwitchFPState)
  1285.  
  1286. /*----------------------------------------------------------------------------
  1287.  *
  1288.  * MachGetCurFPState --
  1289.  *
  1290.  *    MachGetCurFPState(statePtr)
  1291.  *
  1292.  *    Save the current state into *statePtr.
  1293.  *
  1294.  * Results:
  1295.  *         None.
  1296.  *
  1297.  * Side effects:
  1298.  *    None.
  1299.  *
  1300.  *----------------------------------------------------------------------------
  1301.  */
  1302. LEAF(MachGetCurFPState)
  1303.     subu    sp, sp, STAND_FRAME_SIZE
  1304.     sw    ra, STAND_RA_OFFSET(sp)
  1305.     .mask    0x80000000, (STAND_RA_OFFSET - STAND_FRAME_SIZE)
  1306.  
  1307.     mfc0    t1, MACH_COP_0_STATUS_REG    # Disable interrupts and
  1308.     li    t0, MACH_SR_COP_1_BIT        #    enable the coprocessor
  1309.     mtc0    t0, MACH_COP_0_STATUS_REG
  1310.  
  1311. .set noreorder
  1312.     /*
  1313.      * First read out the status register to make sure that all FP
  1314.      * operations have completed.
  1315.      */
  1316.     cfc1    t0, MACH_FPC_CSR
  1317.     nop
  1318.     sw    t0, MACH_FP_SR_OFFSET(a0)
  1319.     /* 
  1320.      * Save the floating point registers.
  1321.      */
  1322.     SAVE_CP1_REG(0); SAVE_CP1_REG(1); SAVE_CP1_REG(2); SAVE_CP1_REG(3)
  1323.     SAVE_CP1_REG(4); SAVE_CP1_REG(5); SAVE_CP1_REG(6); SAVE_CP1_REG(7)
  1324.     SAVE_CP1_REG(8); SAVE_CP1_REG(9); SAVE_CP1_REG(10); SAVE_CP1_REG(11)
  1325.     SAVE_CP1_REG(12); SAVE_CP1_REG(13); SAVE_CP1_REG(14); SAVE_CP1_REG(15)
  1326.     SAVE_CP1_REG(16); SAVE_CP1_REG(17); SAVE_CP1_REG(18); SAVE_CP1_REG(19)
  1327.     SAVE_CP1_REG(20); SAVE_CP1_REG(21); SAVE_CP1_REG(22); SAVE_CP1_REG(23)
  1328.     SAVE_CP1_REG(24); SAVE_CP1_REG(25); SAVE_CP1_REG(26); SAVE_CP1_REG(27)
  1329.     SAVE_CP1_REG(28); SAVE_CP1_REG(29); SAVE_CP1_REG(30); SAVE_CP1_REG(31)
  1330.  
  1331.     mtc0    t1, MACH_COP_0_STATUS_REG    # Restore the status register.
  1332.  
  1333.     addu    sp, sp, STAND_FRAME_SIZE
  1334.  
  1335.     j    ra
  1336.     nop
  1337.  
  1338. .set reorder
  1339. END(MachGetCurFPState)
  1340.  
  1341. /*----------------------------------------------------------------------------
  1342.  *
  1343.  * MachFPInterrupt --
  1344.  *
  1345.  *    Handle a floating point interrupt.
  1346.  *
  1347.  * Results:
  1348.  *         MACH_OK
  1349.  *
  1350.  * Side effects:
  1351.  *    None.
  1352.  *
  1353.  *----------------------------------------------------------------------------
  1354.  */
  1355. NON_LEAF(MachFPInterrupt,STAND_FRAME_SIZE,ra)
  1356. /*
  1357.  *    unsigned statusReg;    (in a0)
  1358.  *    unsigned causeReg;    (in a1)
  1359.  *    Address EXC_pc;        (in a2)
  1360.  */
  1361.     subu    sp, sp, STAND_FRAME_SIZE
  1362.     sw    ra, STAND_RA_OFFSET(sp)
  1363.         sw    a2, STAND_FRAME_SIZE + 8(sp)
  1364.  
  1365.     and    t1, a0, MACH_SR_KU_PREV
  1366.     bne    t1, zero, 1f
  1367.     /*
  1368.      * We got an FPU interrupt in kernel mode.
  1369.      * At this point we should do something clever like
  1370.      * simulating the instruction that failed.  Instead
  1371.      * we just clear the FPU status register and let
  1372.      * the job die.
  1373.      */
  1374.     PRINTF("FPU interrupt in Kernel mode\012")
  1375.     /*
  1376.      * Turn on the floating point coprocessor.
  1377.      */
  1378.     mfc0    t0, MACH_COP_0_STATUS_REG
  1379.     or    t1, t0, MACH_SR_COP_1_BIT
  1380.     mtc0    t1, MACH_COP_0_STATUS_REG
  1381.     /*
  1382.      * Some nops are needed here or else the coprocessor
  1383.      * won't be enabled by the time we try to clear the
  1384.      * status register and the kernel will panic with
  1385.      * "coprocessor unusable".
  1386.      */
  1387.     nop
  1388.     nop
  1389.     nop
  1390.     nop
  1391.     /*
  1392.      * Clear the status register.
  1393.      */
  1394.     ctc1    zero, MACH_FPC_CSR
  1395.     j    FPReturn
  1396. 1:
  1397.     /*
  1398.      * Turn on the floating point coprocessor.
  1399.      */
  1400.     mfc0    t0, MACH_COP_0_STATUS_REG
  1401.     or    t1, t0, MACH_SR_COP_1_BIT
  1402.     mtc0    t1, MACH_COP_0_STATUS_REG
  1403.     /* 
  1404.      * Check for a stray interrupt.
  1405.      */
  1406.     lw    t1, machFPCurStatePtr
  1407.     lw    t2, machCurStatePtr
  1408.     beq    t1, t2, 1f
  1409.     /*
  1410.      * We got an interrupt and no one was using the coprocessor.  Clear
  1411.      * the interrupt and complain.
  1412.      */
  1413.     PRINTF("Stray FPU interrupt\012")
  1414.     ctc1    zero, MACH_FPC_CSR
  1415.     j    FPReturn
  1416. 1:
  1417.     /*
  1418.      * Fetch the instruction.
  1419.      */
  1420.     addu    v0, a1, 0
  1421.     bltz    v0, 3f                # Check the branch delay bit.
  1422.     /*
  1423.      * This is not in the branch delay slot so calculate the resulting
  1424.      * PC (epc + 4) into v0 and continue to softfp().
  1425.      */
  1426.     lw    a1, 0(a2)
  1427.     addu    v0, a2, 4
  1428.     lw    t0, machCurStatePtr
  1429.     sw    v0, MACH_USER_PC_OFFSET(t0)
  1430.     b    4f
  1431. 3:
  1432.     /*
  1433.      * This is in the branch delay slot so the branch will have to
  1434.      * be emulated to get the resulting PC.
  1435.      */
  1436.     lw    a0, machCurStatePtr
  1437.     addu    a0, a0, MACH_TRAP_REGS_OFFSET
  1438.     addu    a1, a2, zero
  1439.     cfc1    a2, MACH_FPC_CSR
  1440.     addu    a3, zero, zero
  1441.     jal    MachEmulateBranch    # MachEmulateBranch(regsPtr,instPC,csr,
  1442.                     #            FALSE)
  1443.     lw    t0, machCurStatePtr
  1444.     sw    v0, MACH_USER_PC_OFFSET(t0)
  1445.     /*
  1446.      * Now load the floating-point instruction in the branch delay slot
  1447.      * to be emulated by softfp().
  1448.      */
  1449.     lw    a2, STAND_FRAME_SIZE + 8(sp)    #EXC pc
  1450.     lw    a1, 4(a2)
  1451. 4:
  1452.     /*
  1453.      * Check to see if the instruction to be emulated is a floating-point
  1454.      * instruction.
  1455.      */
  1456.     srl    a3, a1, MACH_OPCODE_SHIFT
  1457.     beq    a3, MACH_OPCODE_C1, 5f
  1458.     /*
  1459.      * Send a floating point exception signal to the current process.
  1460.      */
  1461.     li    a0, MACH_SIGFPE
  1462.     jal    Mach_SendSignal
  1463.     j    FPReturn
  1464.  
  1465. 5:
  1466. #ifndef NO_FLOATING_POINT
  1467.     /*
  1468.      * Finally we can call softfp() where a1 has the instruction to
  1469.      * emulate.
  1470.      */
  1471.     jal    softfp
  1472. #else /* NO_FLOATING_POINT */
  1473.     li    a0, MACH_SIGILL
  1474.     jal    Mach_SendSignal
  1475.     j    FPReturn
  1476.     nop
  1477. #endif /* NO_FLOATING_POINT */
  1478.  
  1479. FPReturn:
  1480.     /*
  1481.      * Turn off the floating point coprocessor.
  1482.      */
  1483.     mfc0    t0, MACH_COP_0_STATUS_REG
  1484.     and    t0, t0, ~MACH_SR_COP_1_BIT
  1485.     mtc0    t0, MACH_COP_0_STATUS_REG
  1486.     /*
  1487.      * Return to our caller.
  1488.      */
  1489.     lw    ra, STAND_RA_OFFSET(sp)
  1490.     addu    sp, sp, STAND_FRAME_SIZE
  1491.     j    ra
  1492.     li    v0, MACH_OK
  1493. END(MachFPInterrupt)
  1494.  
  1495. /*----------------------------------------------------------------------------
  1496.  *
  1497.  * MachSysCall --
  1498.  *
  1499.  *    MachSysCall --
  1500.  *
  1501.  *    Handle a system call.
  1502.  *
  1503.  * Entry Registers:
  1504.  *    t0: system call number.
  1505.  *    t1: magic number to distinguish Sprite system calls from UNIX calls.
  1506.  *
  1507.  * Results:
  1508.  *         None.
  1509.  *
  1510.  * Side effects:
  1511.  *    None.
  1512.  *
  1513.  *----------------------------------------------------------------------------
  1514.  */
  1515. .set noreorder
  1516.     .globl MachSysCall
  1517.     .ent MachSysCall, 0
  1518. MachSysCall:
  1519. /*
  1520.  * Check the magic number.
  1521.  */
  1522.     li        k0, MACH_SYSCALL_MAGIC
  1523.     bne        t1, k0, UNIXSyscall
  1524.     nop
  1525. 1:
  1526.     addu    t7, gp, zero            # Save the user's gp in t7
  1527.     la        gp, _gp                # Switch to the kernel's gp
  1528. /*
  1529.  * See if this system call is valid.
  1530.  */
  1531.     lw        t2, machMaxSysCall        # t2 <= Maximum sys call value.
  1532.     nop
  1533.     addu    t2, t2, 1            
  1534.     sltu    t2, t0, t2            # Is t0 < t2 ?    
  1535.     bne        t2, zero, 1f            # If so then continue on.
  1536.     nop
  1537. /*
  1538.  * System call number is too big.  Return SYS_INVALID_SYSTEM_CALL to
  1539.  * the user.
  1540.  */
  1541.     mfc0    t3, MACH_COP_0_EXC_PC
  1542.     addu    gp, t7, zero
  1543.     li        v0, 0x20002
  1544.     addu    t3, t3, 4
  1545.     j        t3
  1546.     rfe
  1547. /* 
  1548.  * Now we know that we have a good system call number so go ahead and
  1549.  * save state and switch to the kernel's stack.
  1550.  */
  1551. 1:
  1552.     lw        t1, machCurStatePtr
  1553.     addu    t2, sp, zero
  1554.     mfc0    t3, MACH_COP_0_EXC_PC
  1555.     sw        sp, MACH_TRAP_REGS_OFFSET + (SP * 4)(t1)
  1556.     sw        t7, MACH_TRAP_REGS_OFFSET + (GP * 4)(t1)
  1557.     sw        s0, MACH_TRAP_REGS_OFFSET + (S0 * 4)(t1)
  1558.     sw        s1, MACH_TRAP_REGS_OFFSET + (S1 * 4)(t1)
  1559.     sw        s2, MACH_TRAP_REGS_OFFSET + (S2 * 4)(t1)
  1560.     sw        s3, MACH_TRAP_REGS_OFFSET + (S3 * 4)(t1)
  1561.     sw        s4, MACH_TRAP_REGS_OFFSET + (S4 * 4)(t1)
  1562.     sw        s5, MACH_TRAP_REGS_OFFSET + (S5 * 4)(t1)
  1563.     sw        s6, MACH_TRAP_REGS_OFFSET + (S6 * 4)(t1)
  1564.     sw        s7, MACH_TRAP_REGS_OFFSET + (S7 * 4)(t1)
  1565.     sw        s8, MACH_TRAP_REGS_OFFSET + (S8 * 4)(t1)
  1566.     sw        ra, MACH_TRAP_REGS_OFFSET + (RA * 4)(t1)
  1567.     sw        t0, MACH_TRAP_REGS_OFFSET + (T0 * 4)(t1)
  1568.     sw        a0, MACH_TRAP_REGS_OFFSET + (A0 * 4)(t1)
  1569.     sw        a1, MACH_TRAP_REGS_OFFSET + (A1 * 4)(t1)
  1570.     sw        a2, MACH_TRAP_REGS_OFFSET + (A2 * 4)(t1)
  1571.     sw        a3, MACH_TRAP_REGS_OFFSET + (A3 * 4)(t1)
  1572.     sw        v0, MACH_TRAP_REGS_OFFSET + (V0 * 4)(t1)
  1573.     sw        v1, MACH_TRAP_REGS_OFFSET + (V1 * 4)(t1)
  1574.     sw        t3, MACH_USER_PC_OFFSET(t1)
  1575. /*
  1576.  * Change to the kernel's stack, enable interrupts and turn off the
  1577.  * floating point coprocessor.
  1578.  */
  1579.     mfc0    s8, MACH_COP_0_STATUS_REG
  1580.     lw        sp, MACH_KERN_STACK_END_OFFSET(t1)
  1581.     and        s8, s8, ~MACH_SR_COP_1_BIT
  1582.     or        t3, s8, MACH_SR_INT_ENA_CUR
  1583.     mtc0    t3, MACH_COP_0_STATUS_REG
  1584. /*
  1585.  * Instrumentation.  Always bump the counter for the current system
  1586.  * call.  If the call profiling flag is on, call the routine to save the
  1587.  * current time in the PCB and set s4 to non-zero.  Otherwise, set s4 to zero
  1588.  * to indicate that profiling is off.
  1589.  *
  1590.  * t0 currently holds the system call number, t1 points at the current state,
  1591.  * and t2 is the user stack pointer.
  1592.  */
  1593.     sll        s5, t0, 2            # s5 <= syscall offset for int
  1594.                         #    or pointer array  
  1595.     la        t3, sys_NumCalls
  1596.     addu    t3, s5, t3            # t3 <= ptr to counter for
  1597.     lw        t4, 0(t3)            #     this syscall
  1598.     nop
  1599.     addu    t4, t4, 1
  1600.     sw        t4, 0(t3)
  1601.  
  1602.     lw        t3, sys_CallProfiling
  1603.     addu    s0, t1, zero            # s0 <= machCurStatePtr (save)
  1604.     beq        t3, zero, fetchArgs
  1605.     addu    s4, zero, zero            # flag profiling as off
  1606.  
  1607.     addu    s1, a0, zero            # save the syscall arguments
  1608.     addu    s2, a1, zero            #   and user stack ptr
  1609.     addu    s3, a2, zero
  1610.     addu    s4, a3, zero
  1611.     jal        Sys_RecordCallStart
  1612.     addu    s6, t2, zero
  1613.  
  1614.     addu    a0, s1, zero            # restore the syscall args,
  1615.     addu    a1, s2, zero            #   and user stack ptr
  1616.     addu    a2, s3, zero
  1617.     addu    a3, s4, zero
  1618.     addu    t2, s6, zero
  1619.  
  1620.     li        s4, 1                # flag profiling as on
  1621.  
  1622. /*
  1623.  * Now fetch the args.  Important registers are as follows:
  1624.  *
  1625.  *    t2: user's stack pointer (used to fetch arguments)
  1626.  *    s0: points at the current state
  1627.  *    s4: "profiling enabled" flag
  1628.  *    s5: the int/pointer array offset for the current system call.
  1629.  *    s8: status register
  1630.  */
  1631. fetchArgs:
  1632.     la        t3, machArgDispatch
  1633.     addu    t3, s5, t3
  1634.     lw        t3, 0(t3)
  1635.     nop
  1636.     jal        t3                # call MachFetch?Args
  1637.     addu    v0, zero, zero
  1638.  
  1639. /* 
  1640.  * If there was an error reading in the user's arguments, the trap
  1641.  * handler will set v0 to a non-zero value.  So, get the address of
  1642.  * the process's "special handling" flag, which is checked when we
  1643.  * prepare to return to user land.  Once that's done, if there was an
  1644.  * error, bail out without calling the syscall function or doing any
  1645.  * more instrumentation.
  1646.  */
  1647.     lw        s2, proc_RunningProcesses    # s2 <= pointer to running
  1648.                         #       processes array.
  1649.     lw        s1, machKcallTableOffset    # s1 <= Offset of kcall table
  1650.                         #       in proc table entry.
  1651.     lw        s2, 0(s2)            # s2 <= pointer to currently
  1652.     nop                        #       running process
  1653.     addu    s3, s2, s1            # s3 <= pointer to kcall table
  1654.                         #       pointer for currently
  1655.                         #       running    process
  1656.     bne        v0, zero, sysCallReturn
  1657.     addu    s1, s3, 4            # Special handling flag follows
  1658.                         # kcallTable field.  Save a 
  1659.                         # pointer to it in s1.
  1660.  
  1661.     lw        s3, 0(s3)            # s3 <= pointer to kcall table
  1662.     nop
  1663.     addu    s3, s3, s5            # s3 <= pointer to pointer to
  1664.                         #       function to call.
  1665.     lw        s3, 0(s3)            # s3 <= pointer to function.
  1666.     nop
  1667.     jal        s3                # Call the function
  1668.     nop
  1669. /*
  1670.  * More instrumentation.  If system call profiling is still turned on, call
  1671.  * the routine to update the total time for the current call.  Note that the
  1672.  * child of a fork() doesn't follow this path, so only the time the parent
  1673.  * spent in Proc_Fork is recorded.
  1674.  *
  1675.  * The following registers are currently precious: s0, s1, s2, s4, s5, s8, 
  1676.  * and v0.
  1677.  */
  1678.     beq        s4, zero, sysCallReturn        # branch if profiling was off
  1679.     nop                        #   at the start of the call.
  1680.     lw        t0, sys_CallProfiling
  1681.     nop
  1682.     beq        t0, zero, sysCallReturn
  1683.  
  1684.     addu    s3, v0, zero            # save syscall's return value
  1685.     jal        Sys_RecordCallFinish
  1686.     srl        a0, s5, 2            # a0 <= syscall number
  1687.     addu    v0, s3, zero            # restore the return value
  1688. /*
  1689.  * Return to the user.  Assuming there were no errors fetching the user
  1690.  * arguments, we have the following saved information:
  1691.  *
  1692.  *    s0:    machCurStatePtr
  1693.  *    s1:    &(procPtr->specialHandling)
  1694.  *    s2:    procPtr
  1695.  *    s8:    status register
  1696.  *    v0:    return code from the system call
  1697.  */
  1698. sysCallReturn:
  1699.     mtc0    s8, MACH_COP_0_STATUS_REG    # Disable interrupts.
  1700.     nop
  1701.     lw        t0, 0(s1)            # Get special handling flag.
  1702.     nop
  1703.     beq        t0, zero, checkFP        # See if special handling 
  1704.     nop                        #    required
  1705. /*
  1706.  * Need some special handling.
  1707.  */
  1708.     lw        t1, MACH_USER_PC_OFFSET(s0)    # Fetch return PC.
  1709.     or        t0, s8, MACH_SR_INT_ENA_CUR    # Prepare to enable interrupts.
  1710.     addu    t1, t1, 4            # Increment return PC by 4 to
  1711.                         #    get past the syscall inst.
  1712.     sw        t1, MACH_USER_PC_OFFSET(s0)    # Write back the return PC.
  1713.  
  1714.     mtc0    t0, MACH_COP_0_STATUS_REG    # Enable interrupts.
  1715.     sw        v0, MACH_TRAP_REGS_OFFSET + (V0 * 4)(s0)
  1716.  
  1717.     addu    a0, s2, zero
  1718.     jal        MachUserReturn            # Call MachUserReturn(procPtr)
  1719.     nop
  1720. /*
  1721.  * Restore A0, A1 and A2 because these will get changed if a signal handler
  1722.  * is to be called.
  1723.  */
  1724.     lw        k0, MACH_USER_PC_OFFSET(s0)
  1725.     lw        a0, MACH_TRAP_REGS_OFFSET + (A0 * 4)(s0)
  1726.     lw        a1, MACH_TRAP_REGS_OFFSET + (A1 * 4)(s0)
  1727.     lw        a2, MACH_TRAP_REGS_OFFSET + (A2 * 4)(s0)
  1728. /*
  1729.  * V1 and A3 are restored for UNIX binary compatibility.
  1730.  */
  1731.     lw        v1, MACH_TRAP_REGS_OFFSET + (V1 * 4)(s0)
  1732.     lw        a3, MACH_TRAP_REGS_OFFSET + (A3 * 4)(s0)
  1733.  
  1734.     beq        v0, zero, sysCallRestore
  1735.     lw        v0, MACH_TRAP_REGS_OFFSET + (V0 * 4)(s0)
  1736.     or        s8, s8, MACH_SR_COP_1_BIT
  1737.     j        sysCallRestore
  1738.     nop
  1739.  
  1740. checkFP:
  1741.     lw        k0, MACH_USER_PC_OFFSET(s0)
  1742.     lw        t0, machFPCurStatePtr
  1743.     addu    k0, k0, 4
  1744.     bne        t0, s0, sysCallRestore
  1745.     nop
  1746.     or        s8, s8, MACH_SR_COP_1_BIT
  1747.  
  1748. /*
  1749.  * Restore the registers.
  1750.  */
  1751.  
  1752. sysCallRestore:
  1753.     mtc0    s8, MACH_COP_0_STATUS_REG
  1754.     lw        sp, MACH_TRAP_REGS_OFFSET + (SP * 4)(s0)
  1755.     lw        gp, MACH_TRAP_REGS_OFFSET + (GP * 4)(s0)
  1756.     lw        s1, MACH_TRAP_REGS_OFFSET + (S1 * 4)(s0)
  1757.     lw        s2, MACH_TRAP_REGS_OFFSET + (S2 * 4)(s0)
  1758.     lw        s3, MACH_TRAP_REGS_OFFSET + (S3 * 4)(s0)
  1759.     lw        s4, MACH_TRAP_REGS_OFFSET + (S4 * 4)(s0)
  1760.     lw        s5, MACH_TRAP_REGS_OFFSET + (S5 * 4)(s0)
  1761.     lw        s6, MACH_TRAP_REGS_OFFSET + (S6 * 4)(s0)
  1762.     lw        s7, MACH_TRAP_REGS_OFFSET + (S7 * 4)(s0)
  1763.     lw        s8, MACH_TRAP_REGS_OFFSET + (S8 * 4)(s0)
  1764.     lw        ra, MACH_TRAP_REGS_OFFSET + (RA * 4)(s0)
  1765.     lw        s0, MACH_TRAP_REGS_OFFSET + (S0 * 4)(s0)
  1766. /*
  1767.  * Return.
  1768.  */
  1769.     j        k0
  1770.     rfe
  1771.  
  1772. .end MachSysCall
  1773. .set reorder
  1774.  
  1775. /*----------------------------------------------------------------------------
  1776.  *
  1777.  * UNIXSyscall --
  1778.  *
  1779.  *      Handle a new (compatibility) UNIX system call.
  1780.  *
  1781.  * Results:
  1782.  *         None.
  1783.  *
  1784.  * Side effects:
  1785.  *    None.
  1786.  *
  1787.  *----------------------------------------------------------------------------
  1788.  */
  1789. .set noreorder
  1790.     .globl UNIXSyscall
  1791.     .ent UNIXSyscall, 0
  1792. UNIXSyscall:
  1793.  
  1794. newUNIXSyscall:
  1795.     addu    t7, gp, zero            # Save the user's gp in t7
  1796.     la        gp, _gp                # Switch to the kernel's gp
  1797. /*
  1798.  * If we are tracing system calls or we have a signal or long jump return
  1799.  * do it the slow way.  Signal and long jump returns are done the slow way
  1800.  * because they have to do a full restore.
  1801.  */
  1802.     lw        k0, machUNIXSyscallTrace
  1803.     beq        v0, MACH_UNIX_LONG_JUMP_RETURN, Mach_UserGenException
  1804.     nop
  1805.     beq        v0, MACH_UNIX_SIG_RETURN, Mach_UserGenException
  1806.     nop
  1807.     bne        k0, zero, Mach_UserGenException
  1808. /*
  1809.  * See if this system call is valid.
  1810.  */
  1811. doNewSysCall:
  1812.     sw          v0, sysCallNum
  1813. /* 
  1814.  * Save state and switch to the kernel's stack.  Note that we save 
  1815.  * a0 - a2 and v1 because UNIX system call stubs assume that these
  1816.  * won't get modified unless a value is returned in v1.
  1817.  */
  1818.     lw        t1, machCurStatePtr
  1819.     addu    t2, sp, zero
  1820.     mfc0    t3, MACH_COP_0_EXC_PC
  1821.     sw        v0, MACH_TRAP_UNIX_RET_VAL_OFFSET+4(t1)
  1822.     sw        a3, MACH_TRAP_UNIX_RET_VAL_OFFSET+8(t1)
  1823.     sw        sp, MACH_TRAP_REGS_OFFSET + (SP * 4)(t1)
  1824.     sw        t7, MACH_TRAP_REGS_OFFSET + (GP * 4)(t1)
  1825.     sw        s0, MACH_TRAP_REGS_OFFSET + (S0 * 4)(t1)
  1826.     sw        s1, MACH_TRAP_REGS_OFFSET + (S1 * 4)(t1)
  1827.     sw        s2, MACH_TRAP_REGS_OFFSET + (S2 * 4)(t1)
  1828.     sw        s3, MACH_TRAP_REGS_OFFSET + (S3 * 4)(t1)
  1829.     sw        s4, MACH_TRAP_REGS_OFFSET + (S4 * 4)(t1)
  1830.     sw        s5, MACH_TRAP_REGS_OFFSET + (S5 * 4)(t1)
  1831.     sw        s6, MACH_TRAP_REGS_OFFSET + (S6 * 4)(t1)
  1832.     sw        s7, MACH_TRAP_REGS_OFFSET + (S7 * 4)(t1)
  1833.     sw        s8, MACH_TRAP_REGS_OFFSET + (S8 * 4)(t1)
  1834.     sw        ra, MACH_TRAP_REGS_OFFSET + (RA * 4)(t1)
  1835.     sw        a0, MACH_TRAP_REGS_OFFSET + (A0 * 4)(t1)
  1836.     sw        a1, MACH_TRAP_REGS_OFFSET + (A1 * 4)(t1)
  1837.     sw        a2, MACH_TRAP_REGS_OFFSET + (A2 * 4)(t1)
  1838.     sw        v1, MACH_TRAP_REGS_OFFSET + (V1 * 4)(t1)
  1839.     sw        t3, MACH_USER_PC_OFFSET(t1)
  1840. /*
  1841.  * Change to the kernel's stack, enable interrupts and turn off the
  1842.  * floating point coprocessor.
  1843.  */
  1844.     mfc0    s8, MACH_COP_0_STATUS_REG
  1845.     lw        sp, MACH_KERN_STACK_END_OFFSET(t1)
  1846.     and        s8, s8, ~MACH_SR_COP_1_BIT
  1847.     or        t3, s8, MACH_SR_INT_ENA_CUR
  1848.     mtc0    t3, MACH_COP_0_STATUS_REG
  1849. /*
  1850.  * Check if the call number is too big.  If so, set call to 0, since that
  1851.  * is an invalid call.
  1852.  */
  1853.     sltu    t0, v0, MACH_MAX_UNIX_SYSCALL    # t0 <= Maximum sys call value
  1854.     bne        t0,zero, 1f            # If so then continue on
  1855.     nop
  1856.     addu    v0, zero, zero
  1857. /*
  1858.  * Now fetch the args.  The user's stack pointer is in t2 and the 
  1859.  * current state pointer in t1.
  1860.  */
  1861. 1:
  1862.     sll        t0, v0, 3    # t0 <= v0 * 8
  1863.     la        t3, sysUnixSysCallTable
  1864.     addu    t0, t0, t3
  1865.     lw        t3, 4(t0)    # t3 <= number of arguments.
  1866.     addu    s3, v0, zero    # Save syscall type in s3.
  1867.     addu    s1, t0, zero    # Save syscall index in s1
  1868.     sll        t3, t3, 2
  1869.     la        t4, machArgDispatchTable
  1870.     addu    t3, t3, t4
  1871.     lw        t3, 0(t3)    # t3 <= pointer to arg fetch routine.
  1872.     nop
  1873.     jal        t3
  1874.     addu    v0, zero, zero
  1875.     bne        v0, zero, unixNewSyscallReturn
  1876.     addu    s0, t1, zero            # Save pointer to current state
  1877.                         #    in s0
  1878.  
  1879. /* 
  1880.  * We got the args now call the routine.
  1881.  */
  1882.     lw        t3, 0(s1)    # t3 <= routine to call.
  1883.     nop
  1884.     jal        t3        # Call the routine.
  1885.     nop
  1886.  
  1887. /*
  1888.  * Return to the user.  We have the following saved information:
  1889.  *    s0:    machCurStatePtr
  1890.  *    s3:    syscall type.
  1891.  *    s8:    status register.
  1892.  */
  1893. unixNewSyscallReturn:
  1894.     lw        s2, proc_RunningProcesses    # s2 <= pointer to running
  1895.                         #       processes array.
  1896.     lw        s1, machKcallTableOffset    # s1 <= Offset of kcall table
  1897.                         #       in proc table entry.
  1898.     lw        s2, 0(s2)            # s2 <= pointer to currently
  1899.                         #       running process
  1900.     addu    s1, s1, 4            # Special handling flag follows
  1901.                         # kcallTable field. 
  1902.     addu    s1, s2, s1            # s1 <= pointer to special
  1903.                         #       handling flag.
  1904. /*
  1905.  * We now have the following saved information:
  1906.  *
  1907.  *    s0:    machCurStatePtr
  1908.  *    s1:    procPtr->specialHandling
  1909.  *    s2:    procPtr
  1910.  *    s3:    syscall type.
  1911.  *    s8:    status register
  1912.  */
  1913. /*
  1914.  * Set up the registers correctly:
  1915.  *
  1916.  *    1) Restore a0, a1, a2 and v1
  1917.  *    2) If status == 0 then regs[a3] <- 0 and v0 <- return value.
  1918.  *       Else regs[A3] <- 1 and v0 <- Compat_MapCode(status).
  1919.  */
  1920. 1:
  1921.     bltz    v0, 3f
  1922.     addu    a3, zero, zero
  1923. 2:
  1924.     lw        a0, MACH_TRAP_REGS_OFFSET + (A0 * 4)(s0)
  1925.     lw        a1, MACH_TRAP_REGS_OFFSET + (A1 * 4)(s0)
  1926.     lw        a2, MACH_TRAP_REGS_OFFSET + (A2 * 4)(s0)
  1927.     lw        v1, MACH_TRAP_REGS_OFFSET + (V1 * 4)(s0)
  1928.     sw        v0, MACH_TRAP_REGS_OFFSET + (V0 * 4)(s0)
  1929.     sw        a3, MACH_TRAP_REGS_OFFSET + (A3 * 4)(s0)
  1930.     j        sysCallReturn
  1931.     nop
  1932. 3:
  1933.     lw          v0, proc_RunningProcesses       # v0 <= pointer to running
  1934.                                                 #       processes array.
  1935.     nop
  1936.     lw          v0, 0(v0)                       # v0 <= pointer to currently
  1937.                                                 #       running process
  1938.     li          a3, 1
  1939.     lw          v0, MACH_UNIX_ERRNO_OFFSET(v0)
  1940.     nop
  1941.     j           2b
  1942.     nop
  1943.  
  1944. .end MachSysCall
  1945. .set reorder
  1946.  
  1947.     .globl MachFetchArgs
  1948. MachFetchArgs:
  1949. /*----------------------------------------------------------------------------
  1950.  *
  1951.  * MachFetch?Args --
  1952.  *
  1953.  *    Fetch the given number of arguments from the user's stack and put
  1954.  *    them onto the kernel's stack.  The user's stack pointer is in t2.
  1955.  *
  1956.  * Results:
  1957.  *         None.
  1958.  *
  1959.  * Side effects:
  1960.  *    Potentially clobbers t0, t1, t3, t4, t5, t6.
  1961.  *
  1962.  *----------------------------------------------------------------------------
  1963.  */
  1964. .set noreorder
  1965.     .globl MachFetch0Args
  1966. MachFetch0Args:
  1967.     j        ra
  1968.     subu    sp, sp, MACH_STAND_FRAME_SIZE
  1969.  
  1970.     .globl MachFetch1Arg
  1971. MachFetch1Arg:
  1972.     lw        t0, 16(t2)    
  1973.     subu    sp, sp, MACH_STAND_FRAME_SIZE + 4
  1974.     j        ra
  1975.     sw        t0, 16(sp)
  1976.  
  1977.     .globl MachFetch2Args
  1978. MachFetch2Args:
  1979.     lw        t0, 16(t2)    
  1980.     lw        t1, 20(t2)
  1981.     subu    sp, sp, MACH_STAND_FRAME_SIZE + 8
  1982.     sw        t0, 16(sp)
  1983.     j        ra
  1984.     sw        t1, 20(sp)
  1985.  
  1986.     .globl MachFetch3Args
  1987. MachFetch3Args:
  1988.     lw        t0, 16(t2)    
  1989.     lw        t1, 20(t2)
  1990.     lw        t3, 24(t2)
  1991.     subu    sp, sp, MACH_STAND_FRAME_SIZE + 12
  1992.     sw        t0, 16(sp)
  1993.     sw        t1, 20(sp)
  1994.     j        ra
  1995.     sw        t3, 24(sp)
  1996.  
  1997.     .globl MachFetch4Args
  1998. MachFetch4Args:
  1999.     lw        t0, 16(t2)    
  2000.     lw        t1, 20(t2)
  2001.     lw        t3, 24(t2)
  2002.     lw        t4, 28(t2)
  2003.     subu    sp, sp, MACH_STAND_FRAME_SIZE + 16
  2004.     sw        t0, 16(sp)
  2005.     sw        t1, 20(sp)
  2006.     sw        t3, 24(sp)
  2007.     j        ra
  2008.     sw        t4, 28(sp)
  2009.  
  2010.     .globl MachFetch5Args
  2011. MachFetch5Args:
  2012.     lw        t0, 16(t2)    
  2013.     lw        t1, 20(t2)
  2014.     lw        t3, 24(t2)
  2015.     lw        t4, 28(t2)
  2016.     lw        t5, 32(t2)
  2017.     subu    sp, sp, MACH_STAND_FRAME_SIZE + 20
  2018.     sw        t0, 16(sp)
  2019.     sw        t1, 20(sp)
  2020.     sw        t3, 24(sp)
  2021.     sw        t4, 28(sp)
  2022.     j        ra
  2023.     sw        t5, 32(sp)
  2024.  
  2025.     .globl MachFetch6Args
  2026. MachFetch6Args:
  2027.     lw        t0, 16(t2)    
  2028.     lw        t1, 20(t2)
  2029.     lw        t3, 24(t2)
  2030.     lw        t4, 28(t2)
  2031.     lw        t5, 32(t2)
  2032.     lw        t6, 36(t2)
  2033.     subu    sp, sp, MACH_STAND_FRAME_SIZE + 24
  2034.     sw        t0, 16(sp)
  2035.     sw        t1, 20(sp)
  2036.     sw        t3, 24(sp)
  2037.     sw        t4, 28(sp)
  2038.     sw        t5, 32(sp)
  2039.     j        ra
  2040.     sw        t6, 36(sp)
  2041.  
  2042. .set reorder
  2043.  
  2044.     .globl MachFetchArgsEnd
  2045. MachFetchArgsEnd:
  2046.  
  2047. /*
  2048.  * Beginning of area where the kernel should be able to handle a bus error
  2049.  * (which includes size errors) while in kernel mode.
  2050.  */
  2051.  
  2052. /*
  2053.  *----------------------------------------------------------------------
  2054.  *
  2055.  * Mach_Probe --
  2056.  *
  2057.  *    Copy a block of memory from one virtual address to another handling
  2058.  *    bus errors that may occur. This    routine is intended to be used to 
  2059.  *    probe for memory mapped devices.
  2060.  *
  2061.  *    The memory interrupt must be enabled for this thing to work.
  2062.  *
  2063.  *    The ds5000 has a few quirks that make this all more complicated
  2064.  *    then it has to be.  First of all, accesses to unpopulated memory
  2065.  *    addresses don't seem to cause any sort of error, so you can't
  2066.  *    use Mach_Probe to figure out how much memory you have.  Second,
  2067.  *    an access to an invalid IO address causes an interrupt.
  2068.  *    Therefore you need to have the memory interrupt enabled to get
  2069.  *    this to work.  A read of an invalid IO address causes both a bus error
  2070.  *    and an interrupt.  The bus error handler will just ignore the bus
  2071.  *    error if it happened in Mach_Probe.  This may not be the best solution
  2072.  *    but it seems to work.
  2073.  *
  2074.  * NOTE: This trap handlers force this routine to return SYS_NO_ACCESS if an
  2075.  *     bus error occurs.
  2076.  *
  2077.  * Calling sequences:
  2078.  *
  2079.  * ReturnStatus
  2080.  * Mach_Probe(size, srcAddress, destAddress)
  2081.  *    int        size;     Size in bytes of the read to do. Must
  2082.  *                  1, 2, 4, or 8  
  2083.  *  Address    srcAddress;     Address to read from. 
  2084.  *  Address    destAddress;     Address to store the read value. 
  2085.  *    
  2086.  *
  2087.  * Results:
  2088.  *    SUCCESS if the copy worked, SYS_NO_ACCESS if there was a bus
  2089.  *    error or IO timeout, FAILURE if the memory interrupt is
  2090.  *    disabled
  2091.  *
  2092.  * Side effects:
  2093.  *    None.
  2094.  *----------------------------------------------------------------------
  2095.  */
  2096. .set noreorder
  2097. LEAF(Mach_Probe)
  2098.     /*
  2099.      * If memory interrupts aren't turned on then we can't do a
  2100.      * probe.
  2101.      */
  2102.     mfc0    t0, MACH_COP_0_STATUS_REG
  2103.     nop
  2104.     and    t0, t0, MACH_INT_MASK_3 | MACH_SR_INT_ENA_CUR
  2105.     beq    t0, MACH_INT_MASK_3 | MACH_SR_INT_ENA_CUR, 1f
  2106.     nop
  2107.     j    ra
  2108.     addu    v0, zero, 1
  2109. 1:
  2110.     addu    v0, zero, 1
  2111.     sw    t0, machInProbe
  2112.     /* a0 is the number of bytes
  2113.      * a1 is the src address
  2114.      * a2 is the dest address
  2115.      */
  2116.     bne     a0,1, Read2Bytes
  2117.     nop
  2118.     lbu     t0, 0(a1)
  2119.     nop
  2120.     sb    t0, 0(a2)
  2121.     b     Done
  2122.     nop
  2123. Read2Bytes:
  2124.     bne     a0, 2, Read4Bytes
  2125.     nop
  2126.     and    t0, a1, 0x1
  2127.     bne    t0, zero, BadRead
  2128.     nop
  2129.     and    t0, a2, 0x1
  2130.     bne    t0, zero, BadRead
  2131.     nop
  2132.     lhu    t0, 0(a1)
  2133.     nop
  2134.     sh    t0, 0(a2)
  2135.     b     Done
  2136.     nop
  2137. Read4Bytes:
  2138.     bne     a0, 4, Read8Bytes
  2139.     nop
  2140.     and    t0, a1, 0x3
  2141.     bne    t0, zero, BadRead
  2142.     nop
  2143.     and    t0, a2, 0x3
  2144.     bne    t0, zero, BadRead
  2145.     nop
  2146.     lw    t0, 0(a1)
  2147.     nop
  2148.     sw    t0, 0(a2)
  2149.     b     Done
  2150.     nop
  2151. Read8Bytes:
  2152.     bne     a0, 8, BadRead
  2153.     nop
  2154.     and    t0, a1, 0x7
  2155.     bne    t0, zero, BadRead
  2156.     nop
  2157.     and    t0, a2, 0x7
  2158.     bne    t0, zero, BadRead
  2159.     nop
  2160.     lw    t0, 0(a1)
  2161.     nop
  2162.     sw    t0, 0(a2)
  2163.     lw    t0, 4(a1)
  2164.     nop    
  2165.     sw    t0, 4(a1)
  2166.     b     Done
  2167.     nop
  2168. BadRead:
  2169.     j    ra
  2170.     addu    v0, zero, 1
  2171. Done:
  2172.     sw    zero, machInProbe
  2173.     j    ra
  2174.     addu    v0, zero, zero
  2175. .set reorder
  2176. END(Mach_Probe)
  2177.  
  2178.